home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 21
/
Cream of the Crop 21 (Terry Blount) (October 1996).iso
/
os2
/
vsoup11.zip
/
newsrc.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-02
|
16KB
|
756 lines
// $Id: newsrc.cc 1.10 1996/09/02 13:26:44 hardy Exp $
//
// This progam/module was written by Hardy Griech based on ideas and
// pieces of code from Chin Huang (cthuang@io.org). Bug reports should
// be submitted to rgriech@ibm.net.
//
// This file is part of soup++ for OS/2. Soup++ including this file
// is freeware. There is no warranty of any kind implied. The terms
// of the GNU Gernal Public Licence are valid for this piece of software.
//
// rg110796:
// - introduction of a hash list because performance was real bad
// - grpFirst/grpNext now returning only subscribed groups
// - newsrc is written if there were any changes (onyl then!)
//
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mts.hh"
#include "newsrc.hh"
#include "util.hh"
TNewsrc::TNewsrc( void )
{
int i;
#ifdef TRACE_ALL
printfT( "TNewsrc::TNewsrc()\n" );
#endif
groups = NULL;
filename = xstrdup("");
cacheGroup = NULL;
cacheGroupName = NULL;
addGroupP = NULL;
fileRead = 0;
for (i = 0; i < hashSize; ++i)
hashTab[i] = (pGroup)NULL;
} // TNewsrc::TNewsrc
TNewsrc::~TNewsrc()
{
Range *rp1, *rp2;
pGroup gp1, gp2;
//// delete filename;
gp1 = groups;
while (gp1 != NULL) {
rp1 = gp1->readList;
while (rp1 != NULL) {
rp2 = rp1->next;
//// delete rp1;
rp1 = rp2;
}
gp2 = gp1->next;
//// delete gp1->name;
//// delete gp1;
gp1 = gp2;
}
} // TNewsrc::~TNewsrc
TNewsrc::Range *TNewsrc::getReadList(FILE *nrcFile)
//
// Read the article numbers from a .newsrc line.
//
{
static const char digits[] = "%[0123456789]";
Range *pLast, *rp, *head;
int lo, hi, c;
char buf[20];
/* Initialize subscription list */
pLast = NULL;
head = NULL;
/* Expect [ \n] */
c = fgetcT(nrcFile);
while (c != '\n' && c != EOF) {
/* Expect number */
if (fscanfT(nrcFile, digits, buf) != 1)
break;
lo = atoi(buf);
/* Get space for new list entry */
rp = new Range;
rp->next = NULL;
/* Expect [-,\n] */
c = fgetcT(nrcFile);
if (c == '-') {
/* Is a range */
/* Expect number */
if (fscanfT(nrcFile, digits, buf) != 1)
break;
hi = atoi(buf);
rp->lo = lo;
rp->hi = hi;
/* Reverse them in case they're backwards */
if (hi < lo) {
rp->lo = hi;
rp->hi = lo;
}
if (rp->lo == 0) //???
rp->lo = 1;
/* Expect [,\n] */
c = fgetcT(nrcFile);
} else {
/* Not a range */
rp->lo = rp->hi = lo;
}
if (rp->lo == 0) { //???
//// delete rp;
continue;
}
/* Check if range overlaps last one */
if (pLast != NULL && rp->lo <= pLast->hi + 1) {
/* Combine ranges */
if (rp->lo < pLast->lo)
pLast->lo = rp->lo;
if (rp->hi > pLast->hi)
pLast->hi = rp->hi;
/* Free old (ehm new?) one */
//// delete rp;
} else {
/* No overlap, update pointers */
if (pLast == NULL) {
head = rp;
} else {
pLast->next = rp;
}
pLast = rp;
}
}
return head;
} // TNewsrc::getReadList
int TNewsrc::readFile( const char *newsrcFile )
//
// Read the .newsrc file.
// Return 0 on error (otherwise 1)
//
{
FILE *nrcFile;
char group_name[BUFSIZ], ch;
#ifdef TRACE_ALL
printfT("TNewsrc::readFile(%s)\n",newsrcFile);
#endif
assert( !fileRead );
/* Open it */
if ((nrcFile = fopenT(newsrcFile, "r")) == NULL) {
fprintfT(stderr, "Cannot open %s\n", newsrcFile);
return 0;
}
filename = xstrdup(newsrcFile);
sema.Request();
/* Read newsgroup entry */
while (fscanfT(nrcFile, "%[^:! \t\n]%*[ \t]", group_name) == 1) {
pGroup np;
if (group_name[0] == '\0')
break;
//
// Allocate a new entry
//
np = (pGroup)grpAdd( group_name );
ch = fgetcT(nrcFile);
if (ch == '\n') {
/* The user didn't end the line with a colon. */
np->subscribed = 1;
} else {
/* Parse subscription list */
np->subscribed = (ch == ':');
np->readList = getReadList(nrcFile);
}
}
fcloseT(nrcFile);
fileRead = 1;
fileChanged = 0;
sema.Release();
return 1;
} // TNewsrc::readFile
void TNewsrc::putReadList(FILE *fd, Range *head)
//
// Write the article numbers for a .newsrc entry.
//
{
if (head == NULL)
fputcT('0',fd);
else {
while (head != NULL) {
if (head->lo == head->hi)
fprintfT(fd, "%ld", head->lo);
else
fprintfT(fd, "%ld-%ld", head->lo, head->hi);
head = head->next;
if (head != NULL)
fputcT(',', fd);
}
}
fputcT('\n', fd);
} // TNewsrc::putReadList
int TNewsrc::writeFile(void)
//
// Rewrite the updated .newsrc file
//
{
char oldFile[FILENAME_MAX];
FILE *nrcFile;
pGroup np;
#ifdef TRACE_ALL
printfT( "TNewsrc::writeFile()\n" );
#endif
if (filename[0] == '\0')
return 1; // successful (cause nothing to do)
if (groups == NULL || !fileRead || !fileChanged)
return 1;
sema.Request();
//
// Back up old .newsrc file.
//
sprintfT(oldFile, "%s.old", filename);
remove(oldFile);
rename(filename, oldFile);
if ((nrcFile = fopenT(filename, "w")) == NULL) {
fprintfT(stderr, "Cannot write %s\n", filename);
sema.Release();
return 0;
}
for (np = groups; np != NULL; np = np->next) {
fputsT(np->name, nrcFile);
fputcT(np->subscribed ? ':' : '!', nrcFile);
fputcT(' ', nrcFile);
putReadList(nrcFile, np->readList);
}
fcloseT(nrcFile);
sema.Release();
return 1;
} // TNewsrc::writeFile
//--------------------------------------------------------------------------------
TNewsrc::pGroup TNewsrc::getGroupP( const char *groupName )
//
// check, if groupName exists (return NULL, if not, otherwise pGroup)
// "cache" is updated
//
{
pGroup np;
pGroup res;
#ifdef TRACE_ALL
// printfT( "TNewsrc::getGroupP(%s)\n", groupName );
#endif
sema.Request();
if (cacheGroupName == NULL || stricmp(groupName,cacheGroupName) != 0) {
int hasho;
hasho = hashi(groupName,hashSize);
for (np = hashTab[hasho]; np != NULL; np = np->hashNext) {
if (stricmp(np->name, groupName) == 0) {
cacheGroupName = np->name;
cacheGroup = np;
break;
}
}
if (np == NULL) {
cacheGroupName = NULL;
cacheGroup = NULL;
}
}
res = cacheGroup;
sema.Release();
#ifdef TRACE_ALL
// printfT( "TNewsrc::getGroupP(%s) = %p\n", groupName,cacheGroup );
#endif
return res;
} // TNewsrc::getGroupP
void TNewsrc::grpFixReadList( const char *groupName, long groupLo, long groupHi )
//
// Sanity fixes to the read article number list
//
{
pGroup np = getGroupP( groupName );
Range *rp1, *rp2;
#ifdef TRACE_ALL
printfT( "TNewsrc::grpFixReadList(%s,%ld,%ld) ",groupName,groupLo,groupHi );
putReadList( stdout, np->readList );
#endif
assert( np != NULL );
sema.Request();
//
// If the highest read article is greater than the highest
// available article, assume the group has been reset.
//
if (np->readList != NULL) {
for (rp1 = np->readList; rp1->next != NULL; rp1 = rp1->next) // find end of list
;
if (rp1->hi > groupHi) {
//
// delete all of the list
//
rp1 = np->readList;
while (rp1 != NULL) {
rp2 = rp1->next;
//// delete rp1;
rp1 = rp2;
}
np->readList = NULL;
}
}
//
// eliminate ranges lower than the lowest available article
// proceed from the beginning of the list...
//
rp1 = np->readList;
while (rp1 != NULL && groupLo > rp1->hi) {
#ifdef DEBUG_ALL
printfT( "ellower: \n" );
putReadList( stdout, np->readList );
#endif
np->readList = rp1->next;
//// delete rp1;
rp1 = np->readList;
}
//
// All entries with a range below groupLo have